use futures_util::TryFutureExt;
use sqlx::{PgPool, Postgres, Transaction};

use crate::{base::errors::AppError, data::{dto::auth_dto::AddRoleRequest, model::role::Role}, repository::QueryBuilder};

pub struct RoleRepository;

/// 权限持久层
/// 
/// **作者：**张翔宇
/// **日期：**2025年9月1日
impl RoleRepository {
    const BASE_INSERT_COLUMN: &'static str = r#"
        code,
        "name",
        description,
        enabled,
        created_by
    "#;

    const BASE_QUERY_SQL: &'static str = r#"
    SELECT
        r.id,
        r.code,
        r."name",
        r.description,
        u.nick_name AS created_by,
        r.enabled,
        r.created_at,
        r.updated_at 
    FROM
        roles r
        LEFT JOIN users u ON r.created_by = u.id
    "#;

    /// 根据用户ID查询其所有关联角色的权限编码
    /// 
    /// # 参数
    /// * `db_pool` - PostgreSQL数据库连接池，用于执行数据库查询
    /// * `user_id` - 要查询的用户ID
    /// 
    /// # 返回值
    /// 成功时返回包含所有权限编码的字符串向量（Vec<String>），
    /// 失败时返回封装了数据库错误信息的AppError
    pub async fn find_auth_code_by_user_id(db_pool: &PgPool, user_id: &i64) -> Result<Vec<String>, AppError> {
        // 执行SQL查询，通过用户ID关联查询其角色对应的权限编码
        // SQL逻辑：关联user_roles（用户角色关联表）和roles（角色表），
        // 通过user_id筛选，获取对应的权限编码（code字段）
        sqlx::query_scalar(
            "SELECT code FROM user_roles u LEFT JOIN roles r on u.role_id = r.id WHERE user_id = $1"
        )
        .bind(user_id)
        .fetch_all(db_pool)
        .await
        .map_err(|e| AppError::Database(e.to_string()))
    }

    /// 检查指定角色名称在数据库中是否已存在
    /// 
    /// # 参数
    /// * `db_pool` - PostgreSQL数据库连接池，用于获取数据库连接
    /// * `name` - 要检查的角色名称
    /// 
    /// # 返回值
    /// 成功时返回`Result<bool, AppError>`，其中`bool`为`true`表示名称已存在，`false`表示不存在；
    /// 失败时返回包含数据库错误信息的`AppError::Database`
    pub async fn name_exsits(db_pool: &PgPool, name: &str) -> Result<bool, AppError> {
        sqlx::query_scalar::<_, bool>(
            "SELECT EXISTS(SELECT 1 FROM roles WHERE name = $1);"
        )
        .bind(name)
        .fetch_one(db_pool)
        .await
        .map_err(|e| AppError::Database(e.to_string()))
    }

    /// 检查指定编码在数据库角色表中是否已存在
    /// 
    /// # 功能说明
    /// 异步查询数据库的`roles`表，判断是否存在`code`字段与传入值匹配的记录
    /// 
    /// # 参数
    /// * `db_pool` - PostgreSQL数据库连接池引用，用于获取数据库连接执行查询
    /// * `code` - 待检查的角色编码字符串
    /// 
    /// # 返回值
    /// - 成功：`Result<bool, AppError>`，其中`bool`为`true`表示编码已存在，`false`表示不存在
    /// - 失败：返回`AppError::Database`类型错误，包含具体数据库操作异常信息
    pub async fn code_exsits(db_pool: &PgPool, code: &str) -> Result<bool, AppError> {
        sqlx::query_scalar::<_, bool>(
            "SELECT EXISTS(SELECT 1 FROM roles WHERE code = $1);"
        )
        .bind(code)
        .fetch_one(db_pool)
        .await
        .map_err(|e| AppError::Database(e.to_string()))
    }

    /// 创建新角色并插入数据库的异步函数
    /// 
    /// # 参数
    /// * `tx` - 数据库事务引用，用于执行SQL操作并支持事务管理
    /// * `user_id` - 创建者的用户ID，将作为`created_by`字段存入数据库
    /// * `data` - 包含角色信息的请求结构体，包含code、name、description等字段
    /// 
    /// # 返回值
    /// 成功时返回新创建的角色信息（Role结构体），失败时返回应用自定义错误（AppError）
    pub async fn create(tx: &mut Transaction<'_, Postgres>, user_id: &i64, data: AddRoleRequest) -> Result<Role, AppError> {
        sqlx::query_as::<_, Role>(
            format!("INSERT INTO roles ({}) VALUES($1, $2, $3, $4, $5) RETURNING *", Self::BASE_INSERT_COLUMN).as_str()
        )
        .bind(data.code)
        .bind(data.name)
        .bind(data.description)
        .bind(data.enabled)
        .bind(user_id)
        .fetch_one(&mut **tx)
        .await
        .map_err(|e| AppError::Database(e.to_string()))
    }

    // 根据角色ID查询角色详情的异步函数
    // 参数：
    // - db_pool: PostgreSQL数据库连接池引用，用于获取数据库连接
    // - id: 要查询的角色ID（i64类型）
    // 返回值：Result类型，成功时返回Role结构体实例，失败时返回自定义的AppError
    pub async fn find_by_id(db_pool: &PgPool, id: &i64) -> Result<Role, AppError> {
        sqlx::query_as::<_, Role>(
            format!("{} WHERE r.id = $1", Self::BASE_QUERY_SQL).as_str()
        )
        .bind(id)
        .fetch_one(db_pool)
        .await
        .map_err(|e| AppError::Database(e.to_string()))
    }

    pub async fn page(db_pool: &PgPool, current: i32, size: i32, name: Option<&str>) -> Result<Vec<Role>, AppError> {
        QueryBuilder::new()
            .sql(Self::BASE_QUERY_SQL.to_string())
            .like("r.name", name)
            .not_equal("r.code", Some("R_SUPER"))
            .paginate(current, size)
            .desc("r.id")
            .query_all(db_pool)
            .await
            .map_err(|e| AppError::BadRequest(format!("查询角色分页报错: {}", e)))
    }

    pub async fn total(db_pool: &PgPool, name: Option<&str>) -> Result<i64, AppError> {
        // 使用查询构建器
        QueryBuilder::new()
            .sql("SELECT COUNT(*) FROM roles".to_string())
            .like("name", name)
            .query_count(db_pool)
            .await
            .map_err(|e| AppError::Runtime(format!("创建查询语言失败: {}", e)))
    }

    
}